package com.minisoft.utils.reportdata;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Console;
import cn.hutool.http.HttpUtil;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.springframework.http.HttpMethod;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author JueSu
 * @description: TODO
 * @date 2024/2/4 9:56
 */
public abstract class HttpExportBase {

    private HttpMethod method;
    private String url;

    private List<String> defaultColumns;
    private List<List<Object>> rows = new ArrayList<>();

    public HttpExportBase(String url, HttpMethod method) {
        this.url = url;
        this.method = method;
    }

    private JSONObject body;
    public JSONObject getBody() {
        if (body == null) {
            body = new JSONObject();
        }
        return body;
    }

    private HashMap<String, String> header;
    public Map<String, String> getHeader() {
        if (header == null) {
            header = new HashMap<>();
            header.put("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36");
            header.put("Content-Type", "application/json");
        }
        return header;
    }

    private Map<String, Object> params;
    public Map<String, Object> getParams() {
        if (params == null) {
            params = new HashMap<>();
        }
        return params;
    }

    /**
     * 一步到位，获取数据+导出到excel
     */
    public void export() {
        fetchData();
        writeToFile();
    }

    public void fetchData() {
        int page = 1;
        setPage(page,getBody(),getParams());
        JSONObject jsonObject = doRequest();
        int totalPage = getTotalPage(jsonObject);
        JSONArray datalist = datalist(jsonObject);
        while (CollUtil.isNotEmpty(datalist)) {
            for (Object o : datalist) {
                JSONObject obj = (JSONObject) o;
                if (defaultColumns == null) {
                    defaultColumns = obj.keySet().stream().collect(Collectors.toList());
                }
                //如果此行需要默认规则导出，否则直接返回false
                if (processItem(obj)) {
                    List<String> columnList = getColumnList();
                    List<Object> row = new ArrayList<>();
                    for (String column : columnList) {
                        row.add(obj.get(column));
                    }
                };
            }
            if (page >= totalPage) {
                break;
            }
            setPage(page++,getBody(),getParams());
            jsonObject = doRequest();
            datalist = datalist(jsonObject);
        }
    }

    public void writeToFile() {
        // Create Excel writer
        String outputFilePath = "D:\\temp/export-"+ DateUtil.format(new Date(), DatePattern.PURE_DATETIME_PATTERN) +".xlsx";
        ExcelWriter writer = ExcelUtil.getWriter(outputFilePath);

        // Set the header row
        writer.writeHeadRow(getColumnList());

        // Write data rows
        writer.write(getRows());

        // Close the writer and save the Excel file
        writer.close();

        System.out.println("done");
    }

    protected List<List<Object>> getRows() {
        return rows;
    }

    protected List<String> getColumnList() {
        return defaultColumns;
    }

    private JSONObject doRequest() {
        String jsonData = null,tempUrl = url;
        if (!getParams().isEmpty()) {
            tempUrl += tempUrl.contains("?") ? "&" : "?";
            tempUrl += HttpUtil.toParams(getParams());
        }
        Console.log("params = {}", getDebuggerParams());
        if (HttpMethod.GET.equals(method)) {
            jsonData = HttpUtil.createGet(tempUrl).headerMap(getHeader(), true).execute().body();
        } else {
            jsonData = HttpUtil.createPost(tempUrl).headerMap(getHeader(), true).body(getBody().toString()).execute().body();
        }
        Console.log("result = {}", jsonData);
        return JSON.parseObject(jsonData);
    }

    protected String getDebuggerParams() {
        return JSON.toJSONString(getParams());
    }

    protected abstract void setPage(int page, JSONObject body, Map<String, Object> params);

    protected abstract boolean processItem(JSONObject obj);

    protected abstract JSONArray datalist(JSONObject jsonObject);

    protected abstract int getTotalPage(JSONObject jsonObject);
}
